﻿
#include "pathlib.h"


pathlib::pathlib()
{
	os_sep = *const_cast<char*>(DIR_CHAR);
}


pathlib::~pathlib()
{
}


/*****************************************************************
* Function : string Path(const char* src)
* Description: 对路径字符串进行检查及修正，删除首尾处的非法字符(空格，'\r', '\n', '\t'及结尾处的"."和路径分隔符)
* Calls:  @ string replace_all(string str, string old_value, string new_value)
* Called By:
* Input:  @ const char* src : 待检查的路径字符串
* Output:
* Return: @ string dst : 处理后的路径字符串
* Others:
*****************************************************************/
string pathlib::Path(const char* src)
{
#ifdef _MSC_VER  //WIN32
	const char* pattern_1 = "/";
	const char* pattern_2 = "\\\\";
#else
	const char* pattern_1 = "\\";
	const char* pattern_2 = "//";
#endif

	char* strIn = const_cast<char*>(src);
	char strOut[MAX_PATH_LEN];
	size_t i = 0;
	size_t j = strlen(strIn) - 1;
	while (strIn[i] == ' ' || strIn[i] == '\n'|| strIn[i] == '\r' || strIn[i] == '\t')
		++i;
	while (strIn[j] == ' ' || strIn[j] == '\n' ||strIn[j] == '\r' || strIn[i] == '\t')
		--j;
	strncpy_s(strOut, strIn + i, j - i + 1);
	strOut[j - i + 1] = '\0';
	string src_str = strOut;

	if (src_str.compare(".") == 0 || src_str.compare("..") == 0 || src_str.compare("/") == 0)
	{
		return src_str;
	}
	else
	{
		char strOut_n[MAX_PATH_LEN];
		j = strlen(strOut) - 1;
		while (strOut[j] == '.' || strIn[j] == os_sep)
			--j;
		strncpy_s(strOut_n, strOut, j + 1);
		strOut_n[j + 1] = '\0';
		src_str = strOut_n;

		src_str = replace_all(src_str, pattern_1, DIR_CHAR);
		size_t pos_idx = src_str.find(pattern_2);
		while (pos_idx != string::npos)
		{
			src_str = replace_all(src_str, pattern_2, DIR_CHAR);
			pos_idx = src_str.find(pattern_2);
		}
	}
	//if (isDir)
	//{
	//	string strend;
	//	strend = src[strlen(src) - 1];
	//	if (strend != DIR_CHAR)
	//		dst.append(DIR_CHAR);
	//}
	return src_str;
}


/*****************************************************************
* Function : void CWD(string& str, bool ifshow)
* Description: 获取当前程序所在目录
* Calls:
* Called By:
* Input:  @ string& str : 用来存储结果的路径字符串
*         @ bool ifshow : 是否打印结果，默认为false
* Output:
* Return:
* Others:
*****************************************************************/
void pathlib::CWD(string& str, bool ifshow)
{
	char path_buf[MAX_PATH_LEN];
	char* cwd_path = _getcwd(path_buf, MAX_PATH_LEN);
	str = path_buf;
	if (ifshow == true)
	{
		printf_s("%s", path_buf);  // cwd_path
	}
}


/*****************************************************************
* Function : bool IsExist(const char* src, bool ifshow)
* Description: 对路径字符串进行检查，判断文件或文件夹是否存在
* Calls:  @ string Path(const char* src)
* Called By:
* Input:  @ const char* src : 待检查的路径字符串
*         @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ true : 对象存在
*         @ false : 对象不存在
* Others:
*****************************************************************/
bool pathlib::IsExist(const char* src, bool ifshow)
{
	string fullpath = Path(src);
	if (ACCESS(fullpath.c_str(), 0) == 0)  // != -1
	{
		//if (IsFile(fullpath.c_str())==1)
		//	printf_s("Exists and is a file.\n");
		//else if (IsFile(fullpath.c_str())==0)
		//	rintf_s("Exists and is a folder.\n");
		return true;
	}
	else
	{
		if (ifshow)
			printf_s("%s doesn't exist!\n", src);
		return false;
	}
}


/*****************************************************************
* Function : size_t IsFile(const char* src, bool ifshow)
* Description: 对路径字符串进行检查，判断是否为文件
* Calls:  @ string Path(const char* src)
*         @ bool IsExist(const char* src, bool ifshow)
* Called By:
* Input:  @ const char* src : 待检查的路径字符串
*         @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ 1  : 检查对象是文件
*		  @ 0  : 检查对象是文件夹
*		  @ -1 : 检查对象不存在
* Others:  文件夹名称中如果有'.'，需要另外判断
*****************************************************************/
size_t pathlib::IsFile(const char* src, bool ifshow)
{
	if (IsExist(src))
	{
		string fullpath = Path(src);
		struct _stat buf;
		_stat(fullpath.c_str(), &buf);
		if (_S_IFDIR & buf.st_mode)
		{
			//printf_s("%s is folder!\n", src);
			return 0;
		}
		else if (_S_IFREG & buf.st_mode)
		{
			//printf_s("%s is file\n", src);
			return 1;
		}
		else
		{
			//printf_s("%s don't exist!\n", src);
			return -1;
		}
	}
	else
	{
		string fn = name(src);
		size_t pos_idx = fn.find(".");
		if (pos_idx == string::npos)
		{
			if (ifshow)
				printf_s("%s is not exist and do not have suffix, maybe it is a folder!", src);
			return 0;
		}
		else
		{
			if (ifshow)
				printf_s("%s is not exist and seem to be a file!", src);
			return 1;
		}
	}
}


/*****************************************************************
* Function : bool is_match(const string str, const string pattern)
* Description: 对字符串进行检查，判断是否符合正则表达式
* Calls:
* Called By: @ bool searchFiles(const char* src, vector<string>& itemlist, string pattern, bool recursive);
*            @ bool searchDirs(const char* src, vector<string>& itemlist, string pattern, bool recursive);
* Input:  @ const string str : 待检查的字符串
*         @ const string pattern : 正则表达式模板
* Output:
* Return: @ true or false
* Others: 私有函数
*****************************************************************/
bool pathlib::ifMatch(const string str, const string pattern)
{
	smatch matchResult;
	regex ip_reg(pattern);
	try
	{
		if (regex_match(str, matchResult, ip_reg))
			return true;
		else
			return false;
	}
	catch (regex_error e)
	{
		printf_s("%s\ncode : %s\n", e.what(), e.code());
		exit(0);  //-1
	}
}


/*****************************************************************
* Function : bool searchFiles(const char* src, vector<string>& itemlist, string pattern, bool recursive)
* Description: 深度优先递归遍历当前目录下文件，可指定关键字及是否迭代搜索子文件夹
* Calls: @ string Path(const char* src)
* 		  @ bool IsExist(const char* src, bool ifshow）
* 		  @ int IsFile(const char* src, bool ifshow)
* 		  @ bool ifMatch(const string str, const string pattern)
* Called By:
* Input: @ const char* src : 待搜索的路径字符串
* 		  @ vector<string>& itemlist : 结果储存列表
* 		  @ string pattern : 搜索关键字（正则表达式）
* 		  @ bool recursive : 是否迭代搜索子文件夹
* Output:
* Return: @ vector<string>& itemlist : 搜索结果
* Others:
*****************************************************************/
bool pathlib::searchFiles(const char* src, vector<string>& itemlist, string pattern, bool recursive)
{
	if (IsExist(src) && IsFile(src)==0)
	{
		string fullpath = Path(src);
		fullpath.append(DIR_CHAR);
		intptr_t hFile = 0;				// 文件句柄 long
		struct _finddata_t fileinfo;	//文件信息读取结构
		string p;						//string类很有意思的一个赋值函数:assign()，有很多重载版本
		if ((hFile = _findfirst(p.assign(fullpath).append("*").c_str(), &fileinfo)) != -1)
		{
			do
			{
				if ((fileinfo.attrib & _A_SUBDIR))  //判断是否为文件夹
				{
					if (recursive)
					{
						if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
						{
							string tmp_folder = p.assign(fullpath).append(fileinfo.name);
							searchFiles(tmp_folder.c_str(), itemlist, pattern, recursive);
						}
					}
				}
				else
				{
					if (pattern == "*")
					{
						itemlist.push_back(p.assign(fullpath).append(fileinfo.name));
					}
					else
					{ 
						if (ifMatch(fileinfo.name, pattern))
							itemlist.push_back(p.assign(fullpath).append(fileinfo.name));
					}
				}
			} while (_findnext(hFile, &fileinfo) == 0);  //寻找下一个，成功返回0，否则-1
			_findclose(hFile);
		}
		if (itemlist.size() == 0)
		{
			//printf_s("Don't find any file!\n");
			return false;
		}
	}
	else
	{
		printf_s("ERROR! It seem is a file path or not exist : %s\n", src);
		return false; // exit(0);
	}
	return true;
}


/*****************************************************************
* Function : bool searchDirs(const char* src, vector<string>& itemlist, string pattern, bool recursive)
* Description: 深度优先递归遍历当前目录下文件夹，可指定关键字及是否迭代搜索子文件夹
* Calls:  @ string Path(const char* src)
* 		  @ bool IsExist(const char* src, bool ifshow）
* 		  @ int IsFile(const char* src, bool ifshow)
* 		  @ bool ifMatch(const string str, const string pattern)
* Called By:
* Input:  @ const char*  src : 待搜索的路径字符串
* 		  @ vector<string>& itemlist : 结果储存列表
* 		  @ string pattern : 搜索关键字（正则表达式）
* 		  @ bool recursive : 是否迭代搜索子文件夹
* Output:
* Return: @ vector<string>& itemlist : 搜索结果
* Others:
*****************************************************************/
bool pathlib::searchDirs(const char* src, vector<string>& itemlist, string pattern, bool recursive)
{
	if (IsExist(src) && IsFile(src) == 0)
	{
		string fullpath = Path(src);
		fullpath.append(DIR_CHAR);
		intptr_t hFile = 0;				// 文件句柄 long
		struct _finddata_t fileinfo;	//文件信息读取结构
		string p;
		if ((hFile = _findfirst(p.assign(fullpath).append("*").c_str(), &fileinfo)) != -1)
		{
			do
			{
				if ((fileinfo.attrib & _A_SUBDIR))
				{
					if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					{
						if (pattern == "*")
						{
							itemlist.push_back(p.assign(fullpath).append(fileinfo.name));
						}
						else
						{
							if (ifMatch(fileinfo.name, pattern))
								itemlist.push_back(p.assign(fullpath).append(fileinfo.name));
						}
						if (recursive)
						{
							string tmp_folder = p.assign(fullpath).append(fileinfo.name);
							searchDirs(tmp_folder.c_str(), itemlist, pattern, recursive);
						}
					}
				}
			} while (_findnext(hFile, &fileinfo) == 0);  //寻找下一个，成功返回0，否则-1
			_findclose(hFile);
		}
		if (itemlist.size() == 0)
		{
			//printf_s("Don't find any folder!\n");
			return false;
		}
	}
	else
	{
		printf_s("ERROR! It seem a file path or not exist : %s\n", src);
		return false;
	}
	return true;
}


/*****************************************************************
* Function : string name(const char* src, bool ifshow)
* Description: 获取不带路径的文件或文件夹名
* Calls:  @ string Path(const char* src)
* Called By:
* Input:  @ const char* src : 待检查的路径字符串
*		  @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ string basename : 文件或文件夹名
* Others:
*****************************************************************/
string pathlib::name(const char* src, bool ifshow)
{
	string fullpath = Path(src);
	string basename = "";
	string::size_type iPos = fullpath.find_last_of(DIR_CHAR); // +1;
	if (iPos == string::npos)
	{
		basename = src;
		if (ifshow == true)
			printf_s("%s seems to be root directory or s file path in current work directory!\n", src);
	}
	else
	{
		basename = fullpath.substr(iPos+1, fullpath.length() - iPos);
	}
	return basename;
}


/*****************************************************************
* Function : string stem(const char* src, bool ifshow)
* Description: 获取不带后缀的文件名
* Calls:  @ name(const char* src)
* Called By:
* Input:  @ const char* src : 待检查的路径字符串
*		  @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ string namestem : 不带后缀的文件名，无后缀是返回空字符串""
* Others:
*****************************************************************/
string pathlib::stem(const char* src, bool ifshow)
{
	string basename = name(src);
	string namestem = "";
	// size_t idx = basename.find_last_of(".");
	size_t iPos = basename.rfind(".");
	if (iPos == string::npos)
	{
		if (ifshow == true)
			printf_s("%s seems to be a foler or a file without suffix, so set its suffix as %s!\n", src, DIR_CHAR);
	}
	else
	{
		namestem = basename.substr(0, iPos);
	}
	return namestem;
}


/*****************************************************************
* Function : string parent(const char* src, bool ifshow)
* Description: 获取文件或文件夹的父目录
* Calls:  @ string Path(const char* src)
* Called By:
* Input:  @ const char*  src : 待检查的路径字符串
*		  @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ string pathparent : 父目录，若输入为单个文件名或根目录，返回"."
* Others:
*****************************************************************/
string pathlib::parent(const char* src, bool ifshow)
{
	string pathparent = ".";
	string fullpath = Path(src);
	string::size_type iPos = fullpath.find_last_of(DIR_CHAR);  // +1 防止越界
	if (iPos == string::npos)
	{
	    if (fullpath.compare(DIR_CHAR) == 0)  // "/"
			pathparent = DIR_CHAR;
		else if (fullpath.compare("..") == 0)
			pathparent = "..";
		else //fullpath.compare(".") == 0
			pathparent = ".";
		if (ifshow == true)
			printf_s("%s : It seems to be a single file in current work directory or root directory\n", src);
	}
	else
	{
		pathparent = fullpath.substr(0, iPos);
	}
	return pathparent;
}


/*****************************************************************
* Function : string suffix(const char* src, bool ifshow)
* Description: 获取文件格式
* Calls:  @ name(const char* src)
*         @ IsFile(const char* src, bool ifshow)
* Called By:
* Input:  @ const char*  src : 待检查的路径字符串
*		  @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ string suffix_str : 后缀名，如为无后缀文件，返回字符串"."，若为文件夹，返回路径分隔符并提示。
* Others: 文件夹名称中如果有'.'，需要另外判断
*****************************************************************/
string pathlib::suffix(const char* src, bool ifshow)
{
	string suffix_str = "";
	if (IsExist(src))
	{
		if (IsFile(src) == 1)
		{
			string basename = name(src);
			string::size_type iPos = basename.rfind(".");
			if (iPos == string::npos)
			{
				suffix_str = "";
				if (ifshow == true)
					printf_s("%s is a file without suffix and set the suffix as NULL!", src);
			}
			else
				suffix_str = basename.substr(iPos + 1, basename.length() - iPos);
		}
		else
		{
			if (ifshow == true)
				printf("%s is a folder and set the suffix as %s!\n", src, DIR_CHAR);
			suffix_str = os_sep;
		}
	}
	else
	{
		string basename = name(src);
		//string::size_type iPos = basename.find_last_of(".") + 1;
		string::size_type iPos = basename.rfind(".");  // + 1
		if (iPos == string::npos)
		{
			if (ifshow == true)
				printf_s("%s is not exist and do not have suffix, maybe it is a folder, set the suffix as %s!\n", src, DIR_CHAR);
			suffix_str = os_sep;
		}
		else
			suffix_str = basename.substr(iPos+1, basename.length() - iPos);
	}
	return suffix_str;
}


/*****************************************************************
* Function : bool mkdirs(const char* src, bool ifshow)
* Description: 从左到右依次判断文件夹是否存在,不存在就创建
* Calls:  @ string Path(const char* src)
*         @ string IsFile(const char* src, bool ifshow)
*         @ string IsExist(const char* src, bool ifshow)
*         @ string parent(const char* src, bool ifshow)
* Called By:
* Input:  @ const char*  src : 需要创建的文件夹路径
*		  @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ bool true or false : 是否创建成功
* Others:
*****************************************************************/
bool pathlib::MKDirs(const char* src, bool ifshow)
{
	string tgt_path = "";
	if (IsFile(src) == 1)
		tgt_path = parent(src);
	else
		tgt_path = Path(src);

	if (IsExist(tgt_path.c_str()))
	{
		if (ifshow == true)
			printf_s("%s 已存在!\n", tgt_path.c_str());
		return true;
	}

	if (tgt_path.length() > MAX_PATH_LEN)
	{
		if (ifshow == true)
			printf_s("创建失败, 路径长度超标！\n");
		return false;
	}

	tgt_path.append(DIR_CHAR);
	char tmpDirPath[MAX_PATH_LEN] = { 0 };
	for (size_t i = 0; i < tgt_path.length(); ++i)
	{
		tmpDirPath[i] = tgt_path[i];
		if (tmpDirPath[i] == os_sep)
		{
			if (ACCESS(tmpDirPath, 0) != 0)
			{
				size_t res = MKDIR(tmpDirPath);
				if (res != 0)
				{
					//printf_s("创建失败 ： \n", tmpDirPath);
					return false;
				}
				//else
				//	printf_s("创建成功 ： \n", tmpDirPath);
			}
			//else
			//	printf_s("%s 已存在\n", tmpDirPath);
		}
	}
	//printf_s("创建成功 ： %s\n", src);
	return true;
}


/*****************************************************************
* Function : bool isEmptyFolder(const char* src, bool ifshow)
* Description: 判断文件夹是否为空
* Calls:
* Called By:
* Input:  @ const char* src : 需要进行判断的文件夹
*         @ bool ifshow : 是否输出运行结果，默认为false
* Output:
* Return: @ bool true or false : 目标文件夹是否为空
* Others:
*****************************************************************/
bool pathlib::isEmptyFolder(const char* src, bool ifshow)
{
	if (IsExist(src)==false)
	{
		printf_s("%s do not exist!\n", src);
		return false;
	}
	if (IsFile(src) == 1)
	{
		printf_s("%s is a file path!\n",src);
		return false;
	}
	vector<string> filelist;
	filelist.clear();
	bool flag_files = searchFiles(src, filelist, "*", false);
	vector<string> dirlist;
	dirlist.clear();
	bool flag_dirs = searchDirs(src, dirlist, "*", false);
	if (!flag_files || !flag_dirs)
		return false;
	else
		return true;
}


/*****************************************************************
* Function : bool deleteFile(const char* src)
* Description: 删除文件或文件夹
* Calls:  @ boo isEmptyFolder(const char* src)
*         @ bool IsExist(const char* src, bool ifshow)
*         @ int IsFile(const char* src, bool ifshow)
* Called By:
* Input:  @ const char* src : 需要删除的文件或问价
* Output:
* Return: @ bool true or false : 是否产出成功
* Others:  文件夹搜索删除部分待完善
*****************************************************************/
bool pathlib::deleteFile(const char* src)
{
	if (IsExist(src))
	{
		if (IsFile(src) == 0)
		{
			if (isEmptyFolder(src))
			{
				if (removeEmptyFolder(src))
					return true;
				else
					return false;
			}
			else
			{
				vector<string> filelist;
				filelist.clear();
				if (searchFiles(src, filelist, "*", true))
				{
					for (size_t i = 0; i < filelist.size(); ++i)
					{
						if (!deleteFile(filelist[i].c_str()))
						{
							perror("remove error ");
							return false;
						}
					}
				}
				vector<string> dirlist;
				dirlist.clear();
				if (searchDirs(src, dirlist, "*", true))
				{
					for (size_t i = 0; i < dirlist.size(); ++i)
						if (IsExist(dirlist[i].c_str()) && !deleteFile(dirlist[i].c_str()))
						{
							return false;
						}
				}
				if (removeEmptyFolder(src))
					return true;
				else
					return false;
			}
		}
		else
		{
			string tgt = Path(src);
			if (remove(tgt.c_str()) == 0)
				return true;
			else
			{
				perror("remove error ");
				return false;
			}
		}
	}
	else
	{
		printf_s("%s do not exist!", src);
		return false;
	}
}


/*****************************************************************
* Function : bool removeEmptyFolder(const char* src)
* Description: 删除空文件夹
* Calls:
* Called By:
* Input:  @ const char* src : 需要删除的文件夹
* Output:
* Return: @ bool true or false : 是否删除成功
* Others: 私有函数
*****************************************************************/
bool pathlib::removeEmptyFolder(const char* src)
{
	string tgt_src = Path(src);
	if (RMDIR(tgt_src.c_str()) == 0)
		return true;
	else
	{
		perror("remove error ");
		return false;
	}
}


/*****************************************************************
* Function : bool renameFile(const char* src, const char* dst, bool ifdelete)
* Description: 重命名文件或文件夹
* Calls:  @ bool IsExist(const char* src, bool ifshow)
*		  @ bool deleteFile(const char* src)
* Called By:
* Input:  @ const char* src : 需要重命名的文件或问价
*		  @ const char* dst : 重命名结果
*		  @ bool ifdelete : 目标存在时是否删除
* Output:
* Return: @ bool true or false : 是否重命名成功
* Others:
*****************************************************************/
bool pathlib::renameFile(const char* src, const char* dst, bool ifdelete, bool ifshow)
{
	if (!IsExist(src))
	{
		if (ifshow)
			printf_s("%s : source path is not exist!\n", src);
		return false;
	}

	if (IsExist(dst))
	{
		if (ifdelete==true)
		{
			if (ifshow)
				printf_s("%s : target path is exist and delete it!\n", dst);
			if (!deleteFile(dst))
				return false;
		}
		else
		{
			if (ifshow)
				printf_s("%s : target path is exist and don't choose to delete it,  exit rename process!", dst);
			return false;
		}
	}

	string src_parent = parent(src);
	string dst_parent = parent(dst);
	string src_tgt = name(src);
	string dst_tgt = name(dst);
	size_t flag_1 = src_parent.compare(dst_parent);  // int flag = strcmp(p1.c_str(), p2.c_str());
	size_t flag_2 = src_tgt.compare(dst_tgt);
	size_t ret;
	if (flag_1 == 0)
	{
		if (flag_2 == 0)
		{
			if (ifshow)
				printf_s("重命名结果与原路径相同！\n" );
			return false;
		}
		else
		{
			string src_str = Path(src);
			string dst_str = Path(dst);
			ret = rename(src_str.c_str(), dst_str.c_str());
		}
	}
	else
	{
		//if (flag_2 == 0)
		//	cout << "不同文件夹下移动" << endl;
		//else
		//	cout << "不同文件夹下移动且重命名" << endl;
		if (!IsExist(dst_parent.c_str(), false))
		{
			if (!MKDirs(dst_parent.c_str()))
			{
				if (ifshow)
					printf_s("can't create target path : %s", dst_parent);
				return false;
			}
		}
		string src_str = Path(src);
		string dst_str = Path(dst);
		ret = rename(src_str.c_str(), dst_str.c_str());
	}
	if (ret != 0)
		perror("remove error ");
	return false;
}


/*****************************************************************
* Function : bool copyFile(const char* src, const char* dst, bool ifdelete)
* Description: 复制文件或文件夹
* Calls:  @ bool IsExist(const char* src, bool ifshow)
*         @ bool IsFile(const char* src, bool ifshow)
*		  @ bool deleteFile(const char* src)
*         @ string Path(const char* src)
* Called By:
* Input:  @ const char* src : 需要重命名的文件或问价
*		  @ const char* dst : 重命名结果
*		  @ bool ifdelete : 目标存在时是否删除
* Output:
* Return: @ bool true or false : 是否重命名成功
* Others:
*****************************************************************/
bool pathlib::copyFile(const char* src, const char* dst, bool ifdelete)
{
	if (!IsExist(src))
	{
		printf_s("%s ： source path is not exist!\n", src);
		return false;
	}
	if (IsExist(dst))
	{
		if (ifdelete)
		{
			printf_s("%s ：target path is exist and delete it!\n", dst);
			if (!deleteFile(dst))
				return false;
		}
		else
		{
			printf_s("%s : target path is exist, don't choose to delete it and exit rename process!\n", dst);
			return false;
		}
	}
	string src_parent = parent(src);
	string dst_parent = parent(dst);
	string src_tgt = name(src);
	string dst_tgt = name(dst);
	size_t flag_1 = src_parent.compare(dst_parent);
	size_t flag_2 = src_tgt.compare(dst_tgt);
	if (flag_1 == 0)
	{
		if (flag_2 == 0)
		{
			printf_s("目标路径与原路径相同！\n");
			return false;
		}
		else
		{
			//cout << "同文件夹下复制" << endl;
			if (IsFile(src)==1)
			{
				return copy_singlefile(src, dst);
			}
			else
			{
				return copy_folder(src, dst);
			}
		}
	}
	else
	{
		if (!IsExist(dst_parent.c_str()))
		{
			if (!MKDirs(dst_parent.c_str()))
			{
				printf_s("can't create target path : %s\n", dst_parent);
				return false;
			}
		}
		if (IsFile(src) == 1)
		{
			return copy_singlefile(src, dst);
		}
		else
		{
			return copy_folder(src, dst);
		}
	}
}


/*****************************************************************
* Function : bool copy_singlefile(const char* src, const char* dst)
* Description: 复制文件
* Calls:  @ bool IsExist(const char* src, bool ifshow)
*         @ bool IsFile(const char* src, bool ifshow)
*		  @ bool deleteFile(const char* src)
*         @ string Path(const char* src)
* Called By:
* Input:  @ const char* src : 源文件
*		  @ const char* dst : 复制结果
* Output:
* Return: @ bool true or false : 是否复制成功
* Others:
*****************************************************************/
bool pathlib::copy_singlefile(const char* src, const char* dst)
{
	if (!IsExist(parent(dst).c_str()))
	{
		if (!MKDirs(dst))
		{
			printf_s("can not create destination path : %s\n", dst);
			return false;
		}
	}

	if (IsFile(src)!=1)
	{
		printf_s("%s : source path is not a file path!\n", src);
		return false;
	}
	else
	{
		string src_str = Path(src);
		string dst_str = Path(dst);
		FILE* in_file = NULL;
		FILE* out_file = NULL;
		errno_t err;
		err = fopen_s(&in_file, src_str.c_str(), "rb");
		if (err != 0)
		{
			perror(src_str.c_str());
			return false;
		}
		err = fopen_s(&out_file, dst_str.c_str(), "wb");
		if (err != 0)
		{
			perror(dst_str.c_str());
			return false;
		}
		try
		{
			size_t bytes_in, bytes_out;
			size_t len = 0;
			char data[BUFFSIZE] = { 0 };
			while ((bytes_in = fread(data, 1, BUFFSIZE, in_file)) > 0)
			{
				bytes_out = fwrite(data, 1, bytes_in, out_file);
				if (bytes_in != bytes_out)
				{
					perror("Fatal write error.\n");
					return false;
				}
				len += bytes_out;
				//printf("copying file .... %d bytes copy\n", len);
			}
			fclose(in_file);
			fclose(out_file);
			return true;
		}
		catch (exception e)
		{
			cout << e.what() << endl;
			return false;
		}
	}
}


/*****************************************************************
* Function : bool copy_folder(const char* src, const char* dst)
* Description: 复制文件夹
* Calls:  @ bool IsExist(const char* src, bool ifshow)
*         @ bool IsFile(const char* src, bool ifshow)
*		  @ bool deleteFile(const char* src)
*         @ string Path(const char* src)
* Called By:
* Input:  @ const char* src : 源文件
*		  @ const char* dst : 复制结果
* Output:
* Return: @ bool true or false : 是否复制成功
* Others:
*****************************************************************/
bool pathlib::copy_folder(const char* src, const char* dst)
{
	if (!IsExist(parent(dst).c_str()))
	{
		if (!MKDirs(dst))
		{
			printf_s("can not create destination path : %s\n", dst);
			return false;
		}
	}

	string tmpstr;
	vector<string> srcfiles;
	if (!searchFiles(src, srcfiles, "*", true))
		return true;

	string src_str = Path(src);
	string dst_str = Path(dst);
	size_t src_head = src_str.length();
	vector<string> dstfiles;
	for (size_t i = 0; i < srcfiles.size(); i++)
	{
		tmpstr = srcfiles[i];
		dstfiles.push_back(dst_str + tmpstr.substr(src_head, tmpstr.length()));
	}
	for (size_t i = 0; i < dstfiles.size(); i++)
	{
		if (!copy_singlefile(srcfiles[i].c_str(), dstfiles[i].c_str()))
		{
			printf_s("error : can't copy [%s] to [%s]!\n", srcfiles[i].c_str(), dstfiles[i].c_str());
			return false;
		}
	}
	return true;
}



/*****************************************************************
* Function : string pathlib::replace_all(string str, string old_value, string new_value)
* Description: 字符串全部替换
* Calls:
* Called By:
* Input:  @ string str : 源字符串
*		  @ string old_value : 查找的字符串
*         @ string new_value : 替换的新字符串
* Output:
* Return: @ string str : 替换后的字符串
* Others:
*****************************************************************/
string pathlib::replace_all(string str, string old_value, string new_value)
{
	try
	{
		for (string::size_type pos(0); pos != string::npos; pos += new_value.length())
		{
			if ((pos = str.find(old_value, pos)) != string::npos)
			{
				str.replace(pos, old_value.length(), new_value);
			}
			else
			{
				break;
			}
		}
	}
	catch (exception e)
	{
		printf_s("%s/n", e.what());
	}
	return  str;
}


/*****************************************************************
* Function : void pathlib::str_split(const string& src, const string& sep, vector<string>& vec_str)
* Description: 分割字符串
* Calls:
* Called By:
* Input:  @ const string& src : 源字符串
*		  @ onst string& sep : 分割字符
*         @ vector<string>& vec_str : 分割结果
* Output:
* Return:
* Others:
*****************************************************************/
void pathlib::str_split(const string& src, const string& sep, vector<string>& vec_str)
{
	string::size_type start = 0;
	for (string::size_type end = src.find(sep, start); end != string::npos; end = src.find(sep, start))
	{
		if (end > start)
		{
			vec_str.push_back(src.substr(start, end - start));
		}
		start = end + sep.length();
	}
	if (start < src.length())
	{
		vec_str.push_back(src.substr(start, src.length() - start));
	}
}


/*****************************************************************
* Function : int pathlib::checkstr(char* s, char* t, int flag)
* Description: 判断字符串中是否包含某个字符
* Calls:
* Called By:
* Input:  @ char* s : 源字符串
*		  @ char* t : 分割字符
*         @ int flag : 分割结果
* Output:
* Return:
* Others:
*****************************************************************/
int pathlib::checkstr(char* s, char* t, int flag)
{
	size_t lenstr = strlen(t);
	char* q;
	for (; *(s + lenstr); s++)
	{
		if (flag)  // 不区分大小写
		{
			for (q = t; (*s == *q || *s - 32 == *q || *s + 32 == *q) && *q; s++, q++)
				;
		}
		else  //区分大小写
		{
			for (q = t; *s == *q && *q; s++, q++)
				;
		}
		if (!*q)
		{
			return 1;
		}
	}
	return 0;
}


//static char* left(char* dest, const char* src, int n) 
//{
//	char* p = dest;
//	char* q = nullptr;                       //初始化char*类型
//	q = const_cast<char*>(src);
//	//char* q = src;
//	size_t len = strlen(src);
//	if (n > len) 
//	{
//		n = len;
//	}
//	while (n--) *(p++) = *(q++);
//	*(p++) = '\0';
//	return dest;
//}
